package DigitalNetwork;

import java.util.*;

/**
 * A szimulacio vezerlese.
 * <p>
 *
 * </p>
 *
 * @author Ableda Peter
 * @author Andrasi Istvan
 * @author Kamaras Karoly
 * @author Pora Szilard
 *
 * @version 1.0 Build 2011.04.17.
 */
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public class Simulator {

	/** A halozat bemeneteinek listaja. */
	public List<ISource> sources;
	/** A halozat kimeneteinek listaja. */
	public List<IDisplay> displays;
	/** A halozat elemeinek listaja. */
	private List<Unit> units;
	/** Ezen az interfeszen kommunikál a controllerrel.*/
	private ISimulatorListener listener = null;

	/** [Konstruktor]
	 * letrehozza a sources es displays listat.
	 */
	//==========================================================================
	public Simulator() {

		sources = new ArrayList<ISource>();
		displays = new ArrayList<IDisplay>();
		units = new ArrayList<Unit>();

		Main.printMessage("#Simulator letrehozva.");
	}
	//==========================================================================

	/**
	 * Lepteti a bemeneteket.
	 *
	 */
	//==========================================================================
	public void nextIteration() {
		ListIterator<Unit> iU = units.listIterator();
		while (iU.hasNext()) {
			Unit U = iU.next();
			U.resetUpdateCount();
		}
		ListIterator<ISource> i = sources.listIterator();
		while (i.hasNext()) {
			ISource S = i.next();
			S.iterate(true);
		}
	}
	//==========================================================================

	/**
	 * Begyujti a kijelzok ertekeit.
	 *
	 */
	//==========================================================================
	public void collectValues() {
		ListIterator<IDisplay> i = displays.listIterator();
		while (i.hasNext()) {
			IDisplay D = i.next();
			D.getState();
		}
	}
	//==========================================================================

	/**
	 * Visszaadja az adott ID-ju Unitot, ha nem letezik akkor null-t.
	 *
	 * @param unitID A keresett Unit ID-je
	 * @return Ha letezik, akkor a kersett Unit, ha nem letezik, akkor null.
	 */
	//==========================================================================
	public Unit getUnit(String unitID) {
		ListIterator<Unit> i = units.listIterator();
		while (i.hasNext()) {
			Unit U = i.next();
			if (U.getID().equals(unitID)) {
				return U;
			}
		}
		return null;
	}
	//==========================================================================

	/**
	 * Beregisztral egy unit-ot a szimuluciohoz.
	 *
	 * @param unit Az aktualis unit.
	 * @return
	 */
	//==========================================================================
	public void addUnit(Unit unit) {
		this.units.add(unit);

		if (this.listener != null) {
			this.listener.onUnitAdded(unit);
		}

		Main.printMessage("#" + unit.getID() + " hozzaadva a halozathoz");
	}
	//==========================================================================

	/**
	 * Visszaadja az adott ID-ju Source-t, ha nem letezik akkor null-t.
	 *
	 * @param unitID A keresett Source ID-je
	 * @return Ha letezik, akkor a kersett Source, ha nem letezik, akkor null.
	 */
	//==========================================================================
	public Source getSource(String unitID) {
		ListIterator<ISource> i = sources.listIterator();
		while (i.hasNext()) {
			Source S = (Source) i.next();
			if (S.getID().equals(unitID)) {
				return S;
			}
		}
		return null;
	}
	//==========================================================================

	/**
	 * Beregisztral egy bemenetet a szimuluciohoz.
	 *
	 * @param source Az aktualis bemenet.
	 */
	//==========================================================================
	public void addSource(Source source) {
		this.sources.add(source);
	}
	//==========================================================================

	/**
	 * Visszaadja a bemenetek szamat
	 */
	//==========================================================================
	public int getSourceCount() {
		return this.sources.size();
	}
	//==========================================================================

	/**
	 * Beregisztral egy kimenetet a szimulaciohoz.
	 *
	 * @param display Az aktualis kimenet.
	 */
	//==========================================================================
	public void addDisplay(Display display) {
		this.displays.add(display);
	}
	//==========================================================================

	/**
	 * Visszaadja a kimenetek szamat
	 * @return
	 */
	//==========================================================================
	public int getDisplayCount() {
		return this.displays.size();
	}
	//==========================================================================

	/**
	 * Ellenorzi, hogy az osszes elem megfeleloen be van-e kotve.
	 * @return Igaz, ha minden port be van kotve.
	 */
	//==========================================================================
	public boolean check() {
		boolean result = true;
		// Minden elemre:
		ListIterator<Unit> i = units.listIterator();
		while (i.hasNext()) {
			Unit U = i.next();
			// Ha jol be van kotve, az eredmenyi igaz marad.
			result = result && U.isReady();
		}
		return result;
	}
	//==========================================================================

	/**
	 * Kilistazza a szimulatorban resztvevo elemeket adott kategoria szerint.
	 *
	 * @param unitCategory A listazni kivant kategoria.
	 */
	//==========================================================================
	public void list(String unitCategory) {
		ListIterator<Unit> i = units.listIterator();
		while (i.hasNext()) {
			Unit U = i.next();
			if (U.getCategory().equalsIgnoreCase(unitCategory)) {
				Main.printMessage(U.print());
			}
		}
	}
	//==========================================================================

	/**
	 * Listener hozzaadasa a halozathoz.
	 * Ezen keresztul kommunikal a controllerrel.
	 *
	 * @param l Halozathoz hozaadando listener.
	 */
	//==========================================================================
	public void addListener(ISimulatorListener l) {
		this.listener = l;
	}
	//==========================================================================

	/**
	 *
	 * @param u1
	 * @param x
	 * @param u2
	 * @param y
	 */
	public void connectUnits(Unit u1, int x, Unit u2, int y) {
		u1.connectUnit(x, u2, y);
		if (this.listener != null) {
			this.listener.onConnection(u1, x, u2, y);
		}
	}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

